﻿using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;

namespace Dal
{
    public class BaseDal<T> where T : class, new()
    {
        public readonly DbContext _db = EFDbContextFactory.GetCurrentDbContext();

        public async Task<T> AddAsync(T entity)
        {
            _db.Entry<T>(entity).State = EntityState.Added;
            await _db.SaveChangesAsync();
            return entity;
        }

        public async Task<T> UpdateAsync(T entity)
        {
            _db.Set<T>().Attach(entity);
            _db.Entry<T>(entity).State = EntityState.Modified;
            await _db.SaveChangesAsync();
            return entity;
        }

        public async Task<bool> DeleteAsync(T entity)
        {
            _db.Set<T>().Attach(entity);
            _db.Entry<T>(entity).State = EntityState.Deleted;
            int result = await _db.SaveChangesAsync();
            return result > 0;
        }

        public async Task<T> GetModelAsync(Expression<Func<T, bool>> whereLambda)
        {
            T _entity = await _db.Set<T>().AsNoTracking().FirstOrDefaultAsync<T>(whereLambda);
            return _entity;
        }

        public async Task<IList<T>> GetListAsync(Expression<Func<T, bool>> whereLambda)
        {
            var _list = await _db.Set<T>().AsNoTracking().Where<T>(whereLambda).ToListAsync();
            return _list;
        }

        public async Task<Tuple<IList<T>, int>> GetPageAsync<S>(int pageSize, int pageIndex, Expression<Func<T, bool>> whereLambda, Expression<Func<T, S>> orderByLambda, bool isAsc)
        {
            var _list = _db.Set<T>().AsNoTracking().Where<T>(whereLambda);
            int totalRecord = _list.Count();
            IList<T> resultList;
            if (isAsc)
                resultList = await _list.OrderBy<T, S>(orderByLambda).Skip(pageSize * (pageIndex - 1)).Take(pageSize).ToListAsync();
            else
                resultList = await _list.OrderByDescending<T, S>(orderByLambda).Skip(pageSize * (pageIndex - 1)).Take(pageSize).ToListAsync();

            return new Tuple<IList<T>, int>(resultList, totalRecord);
        }
    }
}
